﻿using System;
using System.Web;
using System.Runtime.Remoting.Messaging;
using Castle.Windsor;
using Castle.Services.Transaction;

namespace DDDProject.Aspects.Utils
{
    /// <summary>
    /// Castle Utils
    /// </summary>
    public static class CastleUtils
    {
        public const string CONTAINER_STORAGE_KEY = "Castle.ContainerStorageKey";

        /// <summary>
        /// Gets the Windsor IoC Container
        /// </summary>
        /// <returns></returns>
        public static IWindsorContainer GetWindsorContainer()
        {
            IWindsorContainer container = null;

            if (HttpContext.Current != null)
            {
                // Retrieve Windsor container
                IContainerAccessor containerAccessor =
                    HttpContext.Current.ApplicationInstance as IContainerAccessor;

                if (containerAccessor == null)
                {
                    throw new InvalidOperationException("You must extend the HttpApplication in your web project " +
                        "and implement the IContainerAccessor to properly expose your container instance");
                }

                container = containerAccessor.Container;

                if (container == null)
                {
                    throw new InvalidOperationException("The container seems to be unavailable (null) in " +
                        "your HttpApplication subclass");
                }
            }
            else
            {
                object obj = CallContext.GetData(CONTAINER_STORAGE_KEY);

                if (obj != null)
                {
                    // Retrieve Windsor container
                    container = obj as IWindsorContainer;
                }

                if (container == null)
                {
                    throw new InvalidOperationException("The container seems to be unavailable in " +
                            "CallContext store. You must register your container in the CallContext store, with the " +
                            "DDDProject.Aspects.Utils.CastleUtils.CONTAINER_STORAGE_KEY");
                }
            }

            return container;
        }

        /// <summary>
        /// Retrieves the Castle Transaction Manager stored in the IoC container
        /// </summary>
        /// <returns>The Castle Transaction Manager</returns>
        public static ITransactionManager GetTransactionManager()
        {
            // Retrieve IoC container
            IWindsorContainer container = CastleUtils.GetWindsorContainer();

            // Retrieve transaction manager
            ITransactionManager transactionManager = null;

            try
            {
                transactionManager = container.Resolve<ITransactionManager>();
            }
            catch
            {
                throw new InvalidOperationException("It seems that the Castle Transaction Manager is not registered in your container.");
            }

            return transactionManager;
        }
    }
}
